package com.back.security.aspect;

import com.back.security.annotation.RequireRole;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
import java.util.stream.Collectors;

/**
 * RequireRole注解的切面处理类
 * 用于在方法执行前检查用户是否拥有所需的角色权限
 */
@Aspect
@Component
public class RequireRoleAspect {

    /**
     * 环绕通知，在方法执行前后拦截
     */
    @Around("@annotation(com.back.security.annotation.RequireRole)")
    public Object checkRole(ProceedingJoinPoint joinPoint) throws Throwable {
        // 获取当前用户认证信息
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication == null || !authentication.isAuthenticated()) {
            throw new AccessDeniedException("未认证用户");
        }
        
        // 获取方法上的RequireRole注解
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        RequireRole requireRole = method.getAnnotation(RequireRole.class);
        
        // 如果没有指定角色，直接放行
        if (requireRole.value().length == 0) {
            return joinPoint.proceed();
        }
        
        // 获取用户所有权限
        Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
        Collection<String> userRoles = authorities.stream()
                .map(GrantedAuthority::getAuthority)
                .map(role -> role.startsWith("ROLE_") ? role : "ROLE_" + role)
                .collect(Collectors.toList());
        
        // 检查是否拥有所需角色
        boolean hasPermission;
        if (requireRole.allRolesRequired()) {
            // 需要同时拥有所有角色
            hasPermission = Arrays.stream(requireRole.value())
                    .map(role -> role.startsWith("ROLE_") ? role : "ROLE_" + role)
                    .allMatch(userRoles::contains);
        } else {
            // 只需要拥有其中一个角色
            hasPermission = Arrays.stream(requireRole.value())
                    .map(role -> role.startsWith("ROLE_") ? role : "ROLE_" + role)
                    .anyMatch(userRoles::contains);
        }
        
        if (!hasPermission) {
            throw new AccessDeniedException("没有足够的权限");
        }
        
        // 权限验证通过，继续执行原方法
        return joinPoint.proceed();
    }
}